import {
  SetStateAction,
  useState,
  useCallback,
  useRef,
  useEffect,
} from "react";

function useMergeState<T>(
  defaultStateValue: T,
  props?: {
    defaultValue?: T;
    value?: T;
    onChange?: (value: T) => void;
  }
) {
  // 内部 stateValue (默认函数有无传值, 组件初始值)
  // useEffect(propsValue) 非受控 || useCallback(stateValue) 受控
  // 合并 mergedValue(propsValue ?? stateValue)

  const {
    value: propsValue,
    onChange,
    defaultValue,
  } = props || {};

  const [stateValue, setStateValue] = useState<T>(() => {
    if (propsValue !== undefined) {
      return propsValue!;
    } else if (defaultValue !== undefined) {
      return defaultValue!;
    } else {
      return defaultStateValue;
    }
  });

  const isFirstRender = useRef(true);

  useEffect(() => {
    if (
      propsValue === undefined &&
      !isFirstRender.current
    ) {
      setStateValue(propsValue!);
    }
    isFirstRender.current = false;
  }, [propsValue]);

  const mergedValue =
    propsValue === undefined ? stateValue : propsValue;

  function isFunction(value: unknown) {
    return typeof value === "function";
  }

  const setValue = useCallback(
    (value: SetStateAction<T>) => {
      let res = isFunction(value)
        ? value(stateValue)
        : value;
      if (propsValue === undefined) {
        setStateValue(res);
      }
      onChange?.(res);
    },
    [stateValue]
  );

  return [mergedValue, setValue];
}
